 package org.mybatis.util;
 
 import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
@SuppressWarnings("all")
 public class ReflectionUtils
 {
   private static final Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);
 
   public static void setFieldValue(Object object, String fieldName, Object value)
   {
     Field field = getDeclaredField(object, fieldName);
 
     if (field == null) {
       throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
     }
     makeAccessible(field);
     try
     {
       field.set(object, value);
     } catch (IllegalAccessException e) {
       e.printStackTrace();
     }
   }
 
   public static Object getFieldValue(Object object, String fieldName)
   {
     Field field = getDeclaredField(object, fieldName);
 
     if (field == null) {
       throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
     }
     makeAccessible(field);
 
     Object result = null;
     try {
       result = field.get(object);
     }
     catch (IllegalAccessException localIllegalAccessException) {
     }
     return result;
   }
 
   public static Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes, Object[] parameters)
     throws InvocationTargetException
   {
     Method method = getDeclaredMethod(object, methodName, parameterTypes);
     if (method == null) {
       throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
     }
     method.setAccessible(true);
     try
     {
       return method.invoke(object, parameters);
     }
     catch (IllegalAccessException localIllegalAccessException) {
     }
     return null;
   }
 
   protected static Field getDeclaredField(Object object, String fieldName)
   {
     for (Class superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
       try
       {
         return superClass.getDeclaredField(fieldName);
       }
       catch (NoSuchFieldException localNoSuchFieldException) {
       }
     return null;
   }
 
   protected static void makeAccessible(Field field)
   {
     if ((!Modifier.isPublic(field.getModifiers())) || (!Modifier.isPublic(field.getDeclaringClass().getModifiers())))
       field.setAccessible(true);
   }
 
   protected static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes)
   {
     for (Class superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
       try
       {
         return superClass.getDeclaredMethod(methodName, parameterTypes);
       }
       catch (NoSuchMethodException localNoSuchMethodException) {
       }
     return null;
   }
 
   public static Class<?> getSuperClassGenricType(Class<?> clazz)
   {
     return getSuperClassGenricType(clazz, 0);
   }
 
   public static Class<?> getSuperClassGenricType(Class<?> clazz, int index)
   {
     Type genType = clazz.getGenericSuperclass();
 
     if (!(genType instanceof ParameterizedType)) {
       logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
       return Object.class;
     }
 
     Type[] params = ((ParameterizedType)genType).getActualTypeArguments();
 
     if ((index >= params.length) || (index < 0)) {
       logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + params.length);
 
       return Object.class;
     }
     if (!(params[index] instanceof Class)) {
       logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
       return Object.class;
     }
 
     return (Class)params[index];
   }
 
   public static IllegalArgumentException convertToUncheckedException(Exception e)
   {
     if (((e instanceof IllegalAccessException)) || ((e instanceof IllegalArgumentException)) || ((e instanceof NoSuchMethodException)))
     {
       return new IllegalArgumentException("Refelction Exception.", e);
     }
     return new IllegalArgumentException(e);
   }
 }

